--[[								-*- Mode: lua -*-
ClosetGnome_ItemRack

Author: Daphne Pfister <tiiroib02@sneakemail.com>

Thanks to Rabbit for writing ClosetGnome and Gello for writing ItemRack

License

Copyright (c) 2007 Daphne Pfister

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


TODO:
Localize

]]

ClosetGnome_ItemRack = AceLibrary("AceAddon-2.0"):new("AceConsole-2.0","AceEvent-2.0","AceHook-2.1")

local addon = ClosetGnome_ItemRack

local item_rack_character
local old_version
local cg_set_cache
local ir_set_cache
local bank_open
local check_at_bank
local ignore_event

local function linkToItemRackId(link)
	if link then
		if old_version then
			return select(3, link:find("item:([%-%d]+:[%-%d]+:[%-%d]+):[%-%d]+"))
		else
			return select(3, link:find("item:([%-%d:]+):%d+"))
		end
	elseif link == false then
		return 0
	end
	return nil
end

local function itemRackIdToLink(id)
	if not id then return id end
	if id == 0 then return false end

	local bagMin = 0
	local bagMax = 4
	if bank_open then
		bagMin = -1
		bagMax = 11
	end

	for i=0,19 do
		local link = GetInventoryItemLink("player",i)
		if link then
			if id == linkToItemRackId(link) then
				return link
			end
		end
	end
	for bag=bagMin,bagMax do
		for slot=1,GetContainerNumSlots(bag) do
			local link = GetContainerItemLink(bag,slot)
			if link then
				if id == linkToItemRackId(link) then
					return link
				end
			end
		end
	end
	return nil
end


function addon:OnEnable()
	self:RegisterEvent("BANKFRAME_OPENED")
	self:RegisterEvent("BANKFRAME_CLOSED")

	-- Handle ClosetGnome setup
	self:ClosetGnome_Setup()

	-- Handle ItemRack setup
	self:ItemRack_Setup()
end

function addon:BANKFRAME_OPENED()
	bank_open = true
	if check_at_bank then
		self:SyncSets()
	end
end

function addon:BANKFRAME_CLOSED()
	bank_open = nil
end

-- Set Syncing
function addon:SyncSets()
	if not cg_set_cache then return end
	if not ir_set_cache then return end
	check_at_bank = nil

	-- Scan ClosetGnome sets
	for setname in pairs(cg_set_cache) do
		if ir_set_cache[setname] then
			self:ItemRack_DoCompareSet(setname)
		else
			self:ItemRack_DoImportSet(setname)
		end
	end

	-- Scan ItemRack sets
	for setname in pairs(ir_set_cache) do
		-- Only need to worry about sets not known to ClosetGnome
		if not cg_set_cache[setname] then
			self:ClosetGnome_DoImportSet(setname)
		end
	end
end

-- ClosetGnome handling
function addon:ClosetGnome_Setup()
	-- Create a dummy OnProfileEnable function that can be hooked
	-- if it does not exist.
	if not ClosetGnome.OnProfileEnable then
		ClosetGnome.OnProfileEnable = function() end
	end
	self:RegisterEvent("ClosetGnome_AddSet")
	self:RegisterEvent("ClosetGnome_UpdateSet")
	self:RegisterEvent("ClosetGnome_DeleteSet")
	self:Hook(ClosetGnome,"OnProfileEnable","ClosetGnome_OnProfileEnable")
	self:ClosetGnome_Init()
end

function addon:ClosetGnome_Init()
	local sets = ClosetGnome.db.char.set
	if sets then
		cg_set_cache = {}
		for setname in pairs(sets) do
			cg_set_cache[setname] = true
		end
		if ir_set_cache then
			self:SyncSets()
		end
	else
		cg_set_cache = nil
	end
end

function addon:ClosetGnome_OnProfileEnable(obj, ...)
	-- We switched profiles
	self.hooks[ItemRack].OnProfileEnable(obj, ...)
	self:ClosetGnome_Init()
end

function addon:ClosetGnome_AddSet(setname)
	if not cg_set_cache then self:ClosetGnome_Init() end
	cg_set_cache[setname] = true
	if not ignore_event then
		self:ItemRack_DoImportSet(setname)
	end
end

function addon:ClosetGnome_UpdateSet(setname)
	if not cg_set_cache then self:ClosetGnome_Init() end
	cg_set_cache[setname] = true
	if not ignore_event then
		self:ItemRack_DoImportSet(setname)
	end
end

function addon:ClosetGnome_DeleteSet(setname)
	if not cg_set_cache then self:ClosetGnome_Init() end
	cg_set_cache[setname] = nil
	if not ignore_event then
		self:ItemRack_DoDeleteSet(setname)
	end
end

function addon:ClosetGnome_DoImportSet(setname)
	--self:Print("Importing to ClosetGnome: "..setname)
	local sets = ClosetGnome.db.char.set
	local set = {}
	local icon
	if old_version then
		local ir_sets = Rack_User and Rack_User[item_rack_character]
		local ir_set = ( ir_sets and ir_sets.Sets ) and ir_sets.Sets[setname] or ir_sets and ir_sets[setname]
		if not ir_set then
			self:Print("Internal error can not find old style ItemRack: "..setname)
			return
		end
		for slot,item in pairs(ir_set) do
			local id = item and item.id
			local link = itemRackIdToLink(id)
			if id and link == nil then
				-- Can not import this set... an item was not found.
				-- Check the next time we visit a bank
				cg_set_cache[setname] = nil
				if not bank_open then
					check_at_bank = true
				end
				return
			end
			set[slot] = link
		end
		icon = ir_set.icon
	else
		local ir_set = ItemRackUser.Sets[setname]
		if not ir_set or not ir_set.equip then
			self:Print("Internal error can not find ItemRack: "..setname)
			return
		end
		for slot,id in pairs(ir_set.equip) do
			local link = itemRackIdToLink(id)
			if id and link == nil then
				-- Can not import this set... an item was not found.
				-- Check the next time we visit a bank
				cg_set_cache[setname] = nil
				if not bank_open then
					check_at_bank = true
				end
				return
			end
			set[slot] = link
		end
		icon = ir_set.icon
	end
	local event = "ClosetGnome_AddSet"
	if sets[setname] then
		event = "ClosetGnome_UpdateSet"
	end
	sets[setname] = set
	if icon then
		ClosetGnome.db.char.icons[setname] = icon
	end
	cg_set_cache[setname] = true
	local old_ignore_event = ignore_event
	ignore_event = true
	ClosetGnome:TriggerEvent(event, setname)
	ClosetGnome:UpdateSetMenu()
	ClosetGnome:UpdateDisplay()
	ignore_event = old_ignore_event
end

function addon:ClosetGnome_DoDeleteSet(setname)
	self:Print("Deleting from ClosetGnome: "..setname)
	ClosetGnome.db.char.set[setname] = nil
	ClosetGnome.db.char.set[setname] = nil
	cg_set_cache[setname] = nil
	local old_ignore_event = ignore_event
	ignore_event = true
	ClosetGnome:TriggerEvent("ClosetGnome_DeleteSet", setname)
	ClosetGnome:UpdateSetMenu()
	ClosetGnome:UpdateDisplay()
	ignore_event = old_ignore_event
end

-- ItemRack Handling
function addon:ItemRack_Setup()
	item_rack_character = UnitName("player").." of "..GetRealmName()

	if ItemRack_Version and ItemRack_Version < 2 then
		old_version = true
	end

	if old_version then
		self:Hook("ItemRack_Sets_Initialize")
		self:Hook("ItemRack_Sets_Save_OnClick")
		self:Hook("ItemRack_Sets_Remove_OnClick")
		self:ItemRack_Old_Init()
	else
		self:Hook(ItemRack,"InitCore")
		if ItemRackOpt then
			self:HookOptions()
		else
			self:Hook(ItemRack,"ToggleOptions")
		end
		self:ItemRack_New_Init()
	end
end

function addon:ItemRack_Old_Init()
	local sets = Rack_User and Rack_User[item_rack_character]
	sets = sets and sets.Sets
	if sets then
		ir_set_cache = {}
		for setname in pairs(sets) do
			if not setname:find("^ItemRack-") and not setname:find("^Rack-") then
				ir_set_cache[setname] = true
			end
		end
		if cg_set_cache then
			self:SyncSets()
		end
	else
		ir_set_cache = nil
	end
end

function addon:ItemRack_Sets_Initialize(...)
	self.hooks.ItemRack_Sets_Initialize(...)
	self:ItemRack_Old_Init()
end

function addon:ItemRack_Sets_Save_OnClick(...)
	if not ir_set_cache then self:ItemRack_Old_Init() end
	local setname = ItemRack.SelectedName
	self.hooks.ItemRack_Sets_Save_OnClick(...)
	ir_set_cache[setname] = true
	self:ClosetGnome_DoImportSet(setname)
end

function addon:ItemRack_Sets_Remove_OnClick(...)
	local setname = ItemRack.SelectedName
	self.hooks.ItemRack_Sets_Remove_OnClick(...)
	ir_set_cache[setname] = nil
	self:ClosetGnome_DoDeleteSet(setname)
end

function addon:ItemRack_Old_DoImportSet(setname)
	--self:Print("Importing to old style ItemRack: "..setname)
	local cg_set = ClosetGnome.db.char.set[setname]
	local cg_icon = ClosetGnome.db.char.icons[setname]
	local sets = Rack_User and Rack_User[item_rack_character]
	if not sets then return end
	local set = {}
	if cg_icon then
		set.icon = cg_icon
	elseif sets[setname] and sets[setname].icon then
		set.icon = sets[setname].icon
	elseif not set.icon then
		set.icon = ClosetGnome.hasIcon or "Interface\\Icons\\INV_Chest_Cloth_17"
	end
	set.oldsetname = nil
	for slot,item in pairs(cg_set) do
		if item then
			set[slot] = {}
			set[slot].id = linkToItemRackId(item)
			set[slot].name = select(3, GetItemInfo(item))
		end
	end
	sets[setname] = set
	ir_set_cache[setname] = true
	if Baggins_ItemRack and Baggins_ItemRack.CacheSets then
		Baggins_ItemRack:CacheSets()
	end
end

function addon:ItemRack_Old_DoCompareSet(setname)
	--self:Print("Comparing to old style ItemRack: "..setname)
	local cg_set = ClosetGnome.db.char.set[setname]
	local cg_icon = ClosetGnome.db.char.icons[setname]
	local ir_sets = Rack_User and Rack_User[item_rack_character]
	if not ir_sets then return end
	local ir_set = ir_sets.Sets and ir_sets.Sets[setname] or ir_sets[setname]
	if not cg_set or not ir_set then
		self:Print("Internal error could not find: "..setname)
		return
	end
	-- Do not considering icons important... but copy icon if missing.
	if not cg_icon then
		ClosetGnome.db.char.icons[setname] = ir_set.icon
	elseif not ir_set.icon then
		ir_set.icon = cg_icon
	end
	local differ = nil
	for i = 0,19 do
		local cg_item = linkToItemRackId(cg_set[i])
		local ir_item = ir_set[i] and ir_set[i].id
		if cg_item ~= ir_item then
			differ = true
			break
		end
	end
	if differ then
		self:Print("Set: "..setname.." is not the same in ClosetGnome and ItemRack.")
	end
end

function addon:ItemRack_Old_DoDeleteSet(setname)
	self:Print("Deleting from old style ItemRack: "..setname)
	local sets = Rack_User and Rack_User[item_rack_character]
	if sets then sets[setname] = nil end
	ir_set_cache[setname] = nil
	if Baggins_ItemRack and Baggins_ItemRack.CacheSets then
		Baggins_ItemRack:CacheSets()
	end
end

function addon:ItemRack_New_Init()
	local sets = ItemRackUser and ItemRackUser.Sets
	if sets then
		ir_set_cache = {}
		for setname in pairs(sets) do
			if not string.match(setname,"^~") then
				ir_set_cache[setname] = true
			end
		end
		if cg_set_cache then
			self:SyncSets()
		end
	else
		ir_set_cache = nil
	end
end

function addon:InitCore(...)
	self.hooks[ItemRack].InitCore(...)
	self:ItemRack_New_Init()
end

function addon:ToggleOptions(...)
	if not ir_set_cache then self:ItemRack_New_Init() end
	self.hooks[ItemRack].ToggleOptions(...)
	self:Unhook(ItemRack,"ToggleOptions")
	self:HookOptions()
end

function addon:HookOptions()
	self:Hook(ItemRackOpt,"SaveSet")
	self:Hook(ItemRackOpt,"DeleteSet")
end

function addon:SaveSet(...)
	if not ir_set_cache then self:ItemRack_New_Init() end
	local setname = ItemRackOptSetsName:GetText()
	self.hooks[ItemRackOpt].SaveSet(...)
	ir_set_cache[setname] = true
	self:ClosetGnome_DoImportSet(setname)
end

function addon:DeleteSet(...)
	if not ir_set_cache then self:ItemRack_New_Init() end
	local setname = ItemRackOptSetsName:GetText()
	self.hooks[ItemRackOpt].DeleteSet(...)
	ir_set_cache[setname] = nil
	self:ClosetGnome_DoDeleteSet(setname)
end

function addon:ItemRack_DoImportSet(setname)
	if old_version then return self:ItemRack_Old_DoImportSet(setname) end

	--self:Print("Importing to ItemRack: "..setname)

	local cg_set = ClosetGnome.db.char.set[setname]
	local cg_icon = ClosetGnome.db.char.icons[setname]
	local set = ItemRackUser.Sets[setname] or {}
	if cg_icon then
		set.icon = cg_icon
	elseif not set.icon then
		set.icon = ClosetGnome.hasIcon or "Interface\\Icons\\INV_Chest_Cloth_17"
	end
	set.oldset = nil
	set.old = {}
	set.equip = {}
	local equip = set.equip
	for slot,item in pairs(cg_set) do
		equip[slot] = linkToItemRackId(item)
	end
	ItemRackUser.Sets[setname] = set
	ir_set_cache[setname] = true
	if Baggins_ItemRack and Baggins_ItemRack.CacheSets then
		Baggins_ItemRack:CacheSets()
	end
end

function addon:ItemRack_DoCompareSet(setname)
	if old_version then return self:ItemRack_Old_DoCompareSet(setname) end

	--self:Print("Comparing to ItemRack: "..setname)

	local cg_set = ClosetGnome.db.char.set[setname]
	local cg_icon = ClosetGnome.db.char.icons[setname]
	local ir_set = ItemRackUser.Sets[setname]
	if not cg_set or not ir_set then
		self:Print("Internal error could not find: "..setname)
		return
	end
	-- Do not considering icons important... but copy icon if missing.
	if not cg_icon then
		ClosetGnome.db.char.icons[setname] = ir_set.icon
	elseif not ir_set.icon then
		ir_set.icon = cg_icon
	end
	local ir_equip = ir_set.equip
	local differ = nil
	for i = 0,19 do
		local cg_item = linkToItemRackId(cg_set[i])
		local ir_item = ir_equip[i]
		if cg_item ~= ir_item then
			differ = true
			break
		end
	end
	if differ then
		self:Print("Set: "..setname.." is not the same in ClosetGnome and ItemRack.")
	end
end

function addon:ItemRack_DoDeleteSet(setname)
	if old_version then return self:ItemRack_Old_DoDeleteSet(setname) end

	self:Print("Deleting from ItemRack: "..setname)

	ItemRackUser.Sets[setname] = nil
	ir_set_cache[setname] = nil
	if Baggins_ItemRack and Baggins_ItemRack.CacheSets then
		Baggins_ItemRack:CacheSets()
	end
end

